/**
 * Keeps track of item displayed so that the user can go back n in its display history
 * @author zulianp@lu.unisi.ch 
 */

package ch.unisi.inf.projects.java.uom.gui.itemeditor;

import java.util.ArrayList;
import java.util.Stack;

import ch.unisi.inf.projects.java.uom.elements.Element;
import ch.unisi.inf.projects.java.uom.elements.Item;
import ch.unisi.inf.projects.java.uom.elements.ItemClass;
import ch.unisi.inf.projects.java.uom.elements.ItemManager;
import ch.unisi.inf.projects.java.uom.elements.ItemManagerListener;

public final class ItemEditorMemoryStack implements ItemEditorListener, ItemManagerListener{

	private final ItemEditor itemEditor;
	private final Stack<Item> previousItems;
	private final Stack<Item> nextItems;
	private final ArrayList<ItemEditorMemoryStackListener> listeners;
	private Item currentItem;
	private int maxStackSize;
	public ItemEditorMemoryStack(final ItemEditor itemEditor)
	{
		this.maxStackSize = 10;
		this.currentItem = null;
		this.itemEditor = itemEditor;
		this.previousItems = new Stack<Item>();
		this.nextItems = new Stack<Item>();
		this.listeners = new ArrayList<ItemEditorMemoryStackListener>();
		ItemManager.instance().addItemManagerListener(this);
		itemEditor.addListener(this);
	}
	
	
	
	public void selectPreviousItem()
	{
		if(previousItems.size() > 0)
		{
			final Item item = previousItems.pop();
			if(currentItem != null){
				nextItems.push(currentItem);
				fireNextItemChanged(currentItem);
			}
			currentItem = item;
			itemEditor.setItemDisplayed(currentItem);
			Item previousItem = null;
			if(previousItems.size() > 0)
				previousItem = previousItems.peek();
			firePreviousItemChanged(previousItem);	
			if(nextItems.size() >= maxStackSize)
			{
				nextItems.remove(0);
			}
		}
	}
	
	public void selectNextItem()
	{
		if(nextItems.size() > 0)
		{
			final Item item = nextItems.pop();
			if (currentItem != null) {
				previousItems.push(currentItem);
				firePreviousItemChanged(currentItem);
			}
			currentItem = item;
			itemEditor.setItemDisplayed(currentItem);
			Item nextItem = null;
			if(nextItems.size() > 0)
				nextItem = nextItems.peek();
			fireNextItemChanged(nextItem);
			System.out.println(previousItems.size() + " VS " + nextItems.size());
		}
	}
	
	//manage listeners
	
	public void addListener(final ItemEditorMemoryStackListener li)
	{
		listeners.add(li);
	}
	
	public void removeListener(final ItemEditorMemoryStackListener li)
	{
		listeners.remove(li);
	}
	
	//for commands next item prediction (enable disable - display ToolTip Text)
	private void firePreviousItemChanged(final Item item)
	{
		for(final ItemEditorMemoryStackListener li : listeners)
		{
			li.previousItemChanged(item);
		}
	}
	
	private void fireNextItemChanged(final Item item)
	{
		for(final ItemEditorMemoryStackListener li : listeners)
		{
			li.nextItemChanged(item);
		}
	}

	
	
	// ItemEditor listen to methods 
	public void itemChanged(final Item newItem) {
		focusOnItem(newItem);
	}

	
	//unused methods 
	public void itemDeleted() {return;}
	public void itemSaved() {return;}


	//ItemManger Listen to Methods
	public void databaseClosed() {
		previousItems.clear();
		nextItems.clear();
		currentItem = null;
		this.fireNextItemChanged(null);
		this.firePreviousItemChanged(null);
	}

	public void elementDeleted(final Element e) {
		databaseClosed();
	}

	public void focusOnItem(final Item newItem) {

		if(newItem != null) {
			if(currentItem != null && currentItem.getName().equals(newItem.getName())) {
				return;
			}
			
			else if (currentItem != null) {			
				previousItems.push(currentItem);
				firePreviousItemChanged(currentItem);
			}
			currentItem = newItem;
			nextItems.clear();
			this.fireNextItemChanged(null);
			if (previousItems.size() >= maxStackSize)
				previousItems.remove(0);
		}
	}
	
	//unused methods 
	public void databaseOpened() {return;}
	public void elementModified(final Element e) {return;}
	public void itemAdded(final Item i) {return;}
	public void itemClassAdded(final ItemClass c) {return;}
	
}
